﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TempCtr.Model
{
    public enum Log_Type
    {
        System,
        Warning,
        Error,
        Console,
        DeBug
    }

    public static class Log
    {
        private struct LogAndText
        {
            public Log_Type log_Type;
            public string Text;
        }

        #region 事件
        // 定义一个委托
        public delegate void NewLogDel(Log_Type log_Type, string Text);
        // 定义一个事件
        public static event NewLogDel OnNewLog;
        // 引发事件的方法 
        public static void RaiseEvent(Log_Type log_Type, string Text)
        {
            if (OnNewLog == null) return;
            OnNewLog(log_Type, Text);
        }
        #endregion

        #region 字段
        public static List<string> LogList = new List<string>();
        private static int _maxDay = Properties.Settings.Default.LogSaveDay;
        private static string _path = Properties.Settings.Default.LogPath;
        public static bool IsWrite = false;
        private static Queue<LogAndText> Logs = new Queue<LogAndText>();
        #endregion

        #region 属性
        /// <summary>
        /// 最大存储日期
        /// </summary>
        public static int MaxDay
        {
            set { _maxDay = value; }
            get
            {
                return _maxDay;
            }
        }

        /// <summary>
        /// 日志地址
        /// </summary>
        public static string Path { set { _path = value; } get { return _path; } }
        #endregion

        #region 构造函数
        static Log()
        {
            if ((_path == "") || !System.IO.Directory.Exists(_path))
                Path = System.AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\";

            foreach (int v in Enum.GetValues(typeof(Log_Type)))
            {
                string strName = Enum.GetName(typeof(Log_Type), v);

                if (strName == "Console") continue;
                MaintainFile(strName);
            }
        }
        #endregion

        #region 公共方法

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="log_Type">日志类型</param>
        /// <param name="Text">内容</param>
        public static void Write(Log_Type log_Type, string Text)
        {

            try
            {
                RaiseEvent(log_Type, Text);
                var str = DateTime.Now.ToString("HH:mm:ss") + " : " + Text;
                Console.WriteLine(str);
                //LogList.Add(str);

                if (!IsSaveFile(log_Type)) return;
                Logs.Enqueue(new LogAndText() { log_Type = log_Type, Text = str });
                if (IsWrite == false)
                {
                    Task t = new Task(() =>
                    {
                        ToWrite();
                    });
                    t.Start();
                }
                //string postPath = "";
                //postPath = Path + Enum.GetName(typeof(Log_Type), log_Type) + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
                //using (StreamWriter file = new StreamWriter(postPath, true))
                //{
                //    file.WriteLine(str);
                //    file.Close();
                //}
            }
            catch (Exception ex)
            {
                Console.WriteLine("写入错误:" + ex);
            }
        }

        /// <summary>
        /// DeBug输出
        /// </summary>
        /// <param name="Text"></param>
        [Conditional("DEBUG")]
        public static void WriteDeBug(string Text)
        {
            RaiseEvent(Log_Type.DeBug, Text);
            var str = DateTime.Now.ToString("HH:mm:ss") + " : " + Text;
            Console.WriteLine(str);
            //LogList.Add(str);
        }

        /// <summary>
        /// 读取日志文件
        /// </summary>
        /// <param name="log_Type">日志类型</param>
        /// <returns></returns>
        public static List<string> Reid(Log_Type log_Type)
        {
            try
            {
                if (!IsSaveFile(log_Type)) return null;
                string postPath = Path + Enum.GetName(typeof(Log_Type), log_Type) + "\\";
                List<string> fileList = new List<string>();
                string[] files = Directory.GetFiles(postPath, "*.txt");

                foreach (string file in files)
                {
                    fileList.Add(file);
                }
                return fileList;
            }
            catch (Exception ex)
            {
                Console.WriteLine("读取错误:" + ex);
                return null;
            }
        }

        /// <summary>
        /// 读取日志
        /// </summary>
        /// <param name="log_Type">日志类型</param>
        /// <param name="time">日志时间</param>
        /// <returns></returns>
        public static string Reid(Log_Type log_Type, string FileName)
        {
            try
            {
                if (!IsSaveFile(log_Type)) return null;
                string postPath = Path + Enum.GetName(typeof(Log_Type), log_Type) + "\\" + FileName;
                return File.ReadAllText(postPath);
            }
            catch (Exception ex)
            {
                Console.WriteLine("读取错误:" + ex);
                return "读取错误:" + ex;
            }
        }

        /// <summary>
        /// 转移日志位置
        /// </summary>
        /// <param name="newPath"></param>
        public static void ChangPath(string newPath)
        {
            File.Move(Path, newPath);
            Path = newPath;
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 判断是否需要保存
        /// </summary>
        /// <param name="log_Type"></param>
        /// <returns></returns>
        private static bool IsSaveFile(Log_Type log_Type)
        {
            switch (log_Type)
            {
                case Log_Type.Console: return false;
                case Log_Type.DeBug: return false;
                default: return true;
            }
        }

        /// <summary>
        /// 文件维护
        /// </summary>
        /// <param name="FileName"></param>
        private static void MaintainFile(string FileName)
        {
            string path_ststem = Path + FileName;
            if (!Directory.Exists(path_ststem))
            {
                Directory.CreateDirectory(path_ststem);
            }
            DeleteFile(path_ststem, MaxDay);
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="fileDirect"></param>
        /// <param name="saveDay"></param>
        private static void DeleteFile(string fileDirect, int saveDay)
        {
            if (saveDay == 0) return;
            FileAttributes attr = File.GetAttributes(fileDirect);
            if (attr == FileAttributes.Directory)//判断是不是文件夹
            {
                DateTime nowTime = DateTime.Now;
                DirectoryInfo root = new DirectoryInfo(fileDirect);
                FileInfo[] fis = root.GetFiles();
                foreach (FileInfo file in fis)//遍历文件夹
                {
                    TimeSpan ts = nowTime - file.CreationTime;  //当前时间  减去 文件创建时间
                    if (ts.Days > saveDay)   //保存的时间 ；  单位：天
                    {
                        file.Delete(); //删除超过时间的文件夹
                        Console.WriteLine("删除文件:" + file.FullName);
                    }
                }
            }
        }

        private static void ToWrite()
        {
            IsWrite = true;
            while (Logs.Count > 0)
            {
                var log = Logs.Dequeue();
                string postPath = "";
                postPath = Path + Enum.GetName(typeof(Log_Type), log.log_Type) + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
                using (StreamWriter file = new StreamWriter(postPath, true))
                {
                    file.WriteLine(log.Text);
                    file.Close();
                }
            }
            IsWrite = false;
        }
        #endregion
    }
}
